#include "threadA.h"
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <map>
#include "ThreadManager.h"
#include <unistd.h>
#include <string>
#include <time.h>

#define random(x) (rand()%x)

using namespace std;


int CThreadA::setID(int id)
{
    m_id = id;
    return 0;
}

int CThreadA::getID()
{
    return m_id;
}


void CThreadA::handleInt(const int& item, const Theron::Address from)
{
    srand((int)time(0));
    printf("CThreadA receive data with int type: %d \n", item);
    int data = random(100);
    sleep(2);
    Send(data, from);
}

void CThreadA::handleString(const std::string & data, const Theron::Address from)
{
    int num = atoi(data.c_str());
    send2ThreadbyID(num,num);
}

int CThreadA::send2ThreadbyID(int data,int ID)
{
    map<int, Theron::Address>::iterator iter;
    //ThreadManager* threadManager = ThreadManager::instance();
    std::map<int, Theron::Address> temp = ThreadManager::instance()->ID_ADDRESS_MAP;
    iter = ThreadManager::instance()->ID_ADDRESS_MAP.find(ID);
    if (iter != ThreadManager::instance()->ID_ADDRESS_MAP.end())
    {
        Send(data, iter->second);
        return 0;
    }

    return -1;
}

//it has several params
void CThreadA::onTimer(void *args)
{
    int* pInt = nullptr;
    CThreadA* pThread = nullptr;
    time_t timer;
    struct tm *tblock;
    timer = time(NULL);
    tblock = localtime(&timer);
    printf("Local time is: %s  ", asctime(tblock));

    ArgumentM* p_arg = (ArgumentM*)args;// the ArgumentM has two args;
    ArgumentM::iterator itr = p_arg->find(PARAM_ONE);
    if(itr == p_arg->end())
    {
        return;
    }
    pInt = (int*)itr->second;

    itr = p_arg->find(THREAD_ADDRESS);
    if(itr == p_arg->end()){
        return;
    }
    pThread = (CThreadA*)itr->second;

    int timeid = *pInt;
    int num = 0;
    switch(timeid){
        case TIME_ID_ONE:
            pThread->send2ThreadbyID(1,1);

            num = ThreadManager::instance()->m_num++;
            printf("num:%d\n",num);
            printf("TIME ID ONE\n");
            break;
        case TIME_ID_TWO:
            printf("TIME ID TWO\n");
            break;
        default:
            break;
    }
}

//param is just timeid
//void CThreadA::onTimer(void *args)
//{
//    time_t timer;
//    struct tm *tblock;
//    timer = time(NULL);
//    tblock = localtime(&timer);
//    printf("Local time is: %s  ", asctime(tblock));
//
//    string* arg = (string*)args;
//    string str = *arg;
//
//    int timeid = atoi(str.c_str());
//
//    switch(timeid){
//        case TIME_ID_ONE:
//            printf("TIME ID ONE\n");
//            break;
//        case TIME_ID_TWO:
//            printf("TIME ID TWO\n");
//            break;
//        default:
//            break;
//    }
//}

//void CThreadA::onTimer(void *args)
//{
//    time_t timer;
//    struct tm *tblock;
//    timer = time(NULL);
//    tblock = localtime(&timer);
//    printf("Local time is: %s  ", asctime(tblock));
//
//    printf("onTimer(): ");
//
//    int* arg = (int*)args;
//
//    int timeid = *arg;
//
//    printf("%d\n",timeid);
//    switch(timeid){
//        case TIME_ID_ONE:
//            printf("TIME ID ONE\n");
//            break;
//        case TIME_ID_TWO:
//            printf("TIME ID TWO\n");
//            break;
//        default:
//            break;
//    }
//}

//param is just timeid
//void CThreadA::setTimer(int millisecond, int timeid)
//{
//    printf("Timeid:%d\n",timeid);
//    string id = to_string(timeid);
//    m_timerid_map.insert(pair<int,string>(timeid,id));
//
//    map<int,string>::iterator itr = m_timerid_map.find(timeid); //it must can be found
//
//    Timer* t = new Timer();
//
//    t->start(millisecond,&onTimer, reinterpret_cast<void*>(&(itr->second)));
//
//    m_timer_map.insert(pair<int,Timer*>(timeid,t));
//}

//it has several params
void CThreadA::setTimer(int millisecond, int timeid)
{
    printf("Timeid:%d\n",timeid);

    int_timerid_map.insert(pair<int,int>(timeid,timeid));   //first we must save the timeid in int_timerid_map
                                                            //thought the ArgumentM use timeid's address
    map<int,int>::iterator it = int_timerid_map.find(timeid);//it must can be found

    ArgumentM arg;  //secondly we must save the two param(CThread-address and timeid's address) in ArgumentM
    arg.insert(pair<int,void*>(THREAD_ADDRESS, reinterpret_cast<void*>(this)));
    arg.insert(pair<int,void*>(PARAM_ONE, reinterpret_cast<void*>(&(it->second))));

    m_timeargs_map.insert(pair<int,ArgumentM>(timeid,arg)); //third,we should save the ArgumentM in m_timeargs_map
                                                            //thought the ArgumentM is used in onTimer()
    map<int,ArgumentM>::iterator itr = m_timeargs_map.find(timeid);//it must can be found

    Timer* t = new Timer();

    t->start(millisecond,&onTimer, reinterpret_cast<void*>(&(itr->second)));

    m_timer_map.insert(pair<int,Timer*>(timeid,t));
}

void CThreadA::cancelTimer(int timeid)
{
    map<int,Timer*>::iterator itr = m_timer_map.find(timeid);
    if(itr != m_timer_map.end())
    {
        itr->second->stop();
        m_timer_map.erase(itr);
    }

    map<int,int>::iterator it = int_timerid_map.find(timeid);
    if(it != int_timerid_map.end())
    {
        int_timerid_map.erase(it);
    }

    map<int,ArgumentM>::iterator itr1 = m_timeargs_map.find(timeid);
    if(itr1 != m_timeargs_map.end())
    {
        m_timeargs_map.erase(itr1);
    }
}